package org.papervision3d.manipulators {
	import flash.geom.Matrix;
	import org.papervision3d.core.*;
	import org.papervision3d.core.proto.CameraObject3D;
	import flash.events.*;
	/**
	 * a plane surfing tool; lets you fly over a flat plane and zoom into it
	 */
	public class Surfer extends Manipulator {
		// state
		public var camera:CameraObject3D;
		private var x:Number = 0;
		private var y:Number = 0;
		private var zoom:Number = 0;
		private var far:Number = 2000;
		private var near:Number = 1000;
		// startup
		public function Surfer(camera:CameraObject3D,x:Number=0,y:Number=0,zoom:Number=0,far:Number=2000.0,near:Number=1000.0) {
			this.camera = camera;
			this.x = x;
			this.y = y;
			this.zoom = zoom;
			this.far = far;
			this.near = near;
		}
		/***************************************************************/
		/* handle events */
		/***************************************************************/
		private var is_down:Boolean = false;
		private var downx:Number = 0;
		private var downy:Number = 0;
		private var mouse_downx:Number = 0;
		private var mouse_downy:Number = 0;
		private var transform:Matrix3D = new Matrix3D();
		private function numToChar(num:int):String {
			if (num > 47 && num < 58) {
				var strNums:String = "0123456789";
				return strNums.charAt(num - 48);
			} else if (num > 64 && num < 91) {
				var strCaps:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
				return strCaps.charAt(num - 65);
			} else if (num > 96 && num < 123) {
				var strLow:String = "abcdefghijklmnopqrstuvwxyz";
				return strLow.charAt(num - 97);
			} else {
				return num.toString();
			}
		}
		public override function event_key_down(e:KeyboardEvent):void {
			if(e.charCode == 65 || e.charCode == 97) { // A
				zoom = zoom + 1;
				if( zoom > 10 ) zoom = 10;
			}
			if(e.charCode == 68 || e.charCode == 100) { // D
				zoom = zoom - 1;
				if( zoom < 0 ) zoom = 0;
			}
		}
		public override function event_mouse_up(e:MouseEvent):void {
			is_down = false;
		}
		public override function event_mouse_down(e:MouseEvent):void {
			is_down = true;
			downx = x;
			downy = y;
			mouse_downx = e.stageX;
			mouse_downy = e.stageY;
		}
		public override function event_mouse_move(e:MouseEvent):void {
			if(is_down) {
				x = downx + (mouse_downx-e.stageX)/Math.pow(2,zoom);
				y = downx + (mouse_downy-e.stageY)/Math.pow(2,zoom);
			}
		}
		public override function event_mouse_zoom(e:MouseEvent):void {
			if( e.delta > 0 ) zoom = zoom + 1;
			if( e.delta < 0 ) zoom = zoom - 1;
			if( zoom > 10 ) zoom = 10;
			if( zoom < 0 ) zoom = 0;
		}
		public override function update():void {
			transform.n14 = x;
			transform.n24 = y;
			transform.n34 = - ( (far-near) / Math.pow(2,zoom) + near );
			camera.transform = transform;
		}
	}
}
